#ifndef CVX_CAMERA_H
#define CVX_CAMERA_H 1

#include "cvxImage.h"

//camera structure used in rig calibration

class CvxCamera
{
public:
	CvxCamera();
	virtual ~CvxCamera(){};
	
	virtual bool write(FILE *pf); //write papameter to a line of the file
	virtual bool read(FILE *pf);  //read parameter in one line of the file

	//set intrinsic matrix and distortion 
	void setConfigure(float fx, float fy, float cx, float cy, float k1, float k2, float p1, float p2, float k3);
	void setImageSize(int w, int h);
	double f(void);
	double u0(void);
	double v0(void);

	Mat m_intrinsic;  //3*3 matrix double	
	Mat m_distortion; //5*1 matrix (k1, k2, p1, p2[,k3])double
	cv::Size m_imageSize;	
};

//canon xf105
class CvxCanonXF105: public CvxCamera
{
public:
	CvxCanonXF105();
	virtual ~CvxCanonXF105(){};

	void computerPhysicalParameter();
	void undistortion(vector<Point2f>& pts);
	
	//physical parameter of Canon XF 105
	int m_maxZoomLevel;            //0-153, total range is 154
	int m_zoomLevel;               //zoom level in camera LCD panel
	double m_aspectRatio;          //fy/fx
	double m_apertureWidth;        //1/3" type 4.8mm
	double m_apertureHeight;       //          3.6mm
	double m_focalLength;          //focal length, fy, unit mm
	Point2d m_principalPoint;      //principle point in image,unit pixel
	double m_fovx;                 //field of view in degrees along the horizontal sensor axis, ignored so far
	double m_fovy;                 //field of view in degrees along the vertical sensor axis, ignored so fat

};

//canon xf 105 camera rig
class CvxCameraRig
{
public:
	CvxCameraRig(){};
	virtual ~CvxCameraRig(){};

	void read(FILE *pf);
	void write(FILE *pf);
	bool GetOrientation(const vector<Point3f> &objPts, const vector<Point2f>& leftPts, 
						const vector<Point2f> &rightPts);
	// get inter axis by first center of the markers
	// the physical position of first marker is in (-unitLength, -unitLength, 0)
	float GetInterAxis(const vector<Point3f> &objPts, const vector<Point2f>& leftPts, 
					   const vector<Point2f> &rightPts, float unitLength);
	void undistortion(vector<Point2f>& leftPts, vector<Point2f> &rightPts);

	//re projection error in current frames
	bool GetReprojectionError(const vector<Point3f> &objPts, const vector<Point2f>& leftPts, 
							  const vector<Point2f> &rightPts, double &leftErr, double &rightErr);

	CvxCanonXF105 m_leftEye;
	CvxCanonXF105 m_rightEye;	

	Vec3d m_eulerAngle;
	Vec3d m_translationVec;

	Mat m_rotation;      //3 * 3
	Mat m_translation;   //3 * 1
};


//computer alignment from image space
void cvxAlignment(const vector<Point2f> &leftPts, const vector<Point2f> &rightPts, 
				  const int w, const int h, float &zoomRatio,
				  float &verticalOffsetPercent, float &horizontalOffsetPercent);
//computer rotation angle from diagonal line with the horizontal line
void cvxAlignRotation(const vector<Point2f> &leftPts, const vector<Point2f> &rightPts, float &rotAngle);

//computer keystone ratio by comparing the length ratio of left vertical and horizontal 
void cvxAlignKeyStone(const vector<Point2f> &leftPts, const vector<Point2f> &rightPts, float &ratio);

//compute alignment from feature points
bool cvxFeaturePtsAlignment(const vector<Point2f> &leftPts, const vector<Point2f> &rightPts, 
							const int w, const int h, float &zoomRatio,
							float &verticalOffsetPercent, float &horizontalOffsetPercent, 
							float &rotAngle, vector<int> &marginPtsIdx);



#endif